package cn.xiaolang.function.data_structure;

import com.google.common.util.concurrent.RateLimiter;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 实现一个许可桶，固定每秒向其中放 100 个许可
 * 桶的大小是固定的 100，放许可的时候，如果桶满了就放弃，没满就按速率向其中
 * 放
 * 请求获取许可，获取到了可以访问，未获取到则拒绝方法 保证了单机限流 100
 *
 * @author fuhw/Dean
 * @date 2020-04-10
 */
public class FlowLimitByRateLimiter {


    /**
     * 首先通过RateLimiter.create(100);创建一个限流器，参数代表每秒生成的令牌数，
     * 通过
     * limiter.acquire(i);来以阻塞的方式获取令牌，当然也可以通过
     * tryAcquire(int permits, long timeout, TimeUnit unit)
     * 来设置等待超时时间的方式获取令牌，如果超timeout为0，则代表非阻塞，
     * 获取不到立即返回。
     *
     * @param args
     */
    public static void main(String[] args) throws InterruptedException {
        RateLimiter limiter = RateLimiter.create(100);
        AtomicLong successCount = new AtomicLong();
        AtomicLong totalCount = new AtomicLong();
        long start = System.currentTimeMillis();
        while (true) {
            if (limiter.tryAcquire()) {
                successCount.getAndIncrement();
            }
            totalCount.getAndIncrement();

            long consume = (System.currentTimeMillis() - start) / 1000L;
            long qps = consume == 0 ? totalCount.get() : totalCount.get() / consume;
            System.out.println("total:" + totalCount.get() +
                    ",success:" + successCount.get() +
                    ",consume:" + consume + "(s)" +
                    ",qps:" + qps + "/s");
        }
    }

}
